﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.ComponentModel;

namespace NetLogger
{
	public enum NetActivityTypes
	{
		NoActivity,
		Activation,
		Deactivation,
		CheckIn,
		CheckOut,
		NetControlChanged,
		AlternateNetControlChanged,
		SKYWARNLiaisonChanged,
		MobileBaseChanged,
		LocationChanged,
		LocationVerified,
		NewReport,
		FrequencyChanged,
		// Activities beyond this point do not actually generate activity records
		HasTrafficChanged,
		SwapControlAlt,
		ClearNewMembers,
		SelectNextWithTraffic
	}

	public class NetActivity : NetPropertyBase, INetPost, INetMapMarker
	{
		private Guid _id;
		private string _loggerId;
		private int _activationId;

		private bool _needsAck;
		public bool NeedsAck
		{
			get
			{
				return _needsAck;
			}
		}

		private bool _isLocal;
		public bool IsLocal
		{
			get
			{
				return _isLocal;
			}
		}

		private bool _isPriority;
		public bool IsPriority
		{
			get
			{
				return _isPriority;
			}
			private set
			{
				_isPriority = value;
				OnPropertyChanged( "IsPriority" );
			}
		}

		private DateTimeOffset _time;
		public DateTimeOffset Time
		{
			get
			{
				return _time;
			}
			protected set
			{
				_time = value;
				OnPropertyChanged( "TimeString" );
			}
		}

		public string TimeString
		{
			get
			{
				return _time.ToLocalTime().ToString( Properties.Resources.TimeFormat );
			}
		}

		private NetActivityTypes _activityType;
		public string ActivityType
		{
			get
			{
				switch ( _activityType )
				{
					case NetActivityTypes.Activation:
						return Properties.Resources.ActivationActivity;
					case NetActivityTypes.Deactivation:
						return Properties.Resources.DeactivationActivity;
					case NetActivityTypes.CheckIn:
						return Properties.Resources.CheckInActivity;
					case NetActivityTypes.CheckOut:
						return Properties.Resources.CheckOutActivity;
					case NetActivityTypes.NetControlChanged:
						return Properties.Resources.NetControlChangedActivity;
					case NetActivityTypes.AlternateNetControlChanged:
						return Properties.Resources.AlternateNetControlChangedActivity;
					case NetActivityTypes.SKYWARNLiaisonChanged:
						return Properties.Resources.SKYWARNLiaisonChangedActivity;
					case NetActivityTypes.MobileBaseChanged:
						return Properties.Resources.MobileBaseChangedActivity;
					case NetActivityTypes.LocationChanged:
						return Properties.Resources.LocationChangedActivity;
					case NetActivityTypes.LocationVerified:
						return Properties.Resources.LocationVerifiedActivity;
					case NetActivityTypes.NewReport:
						return Properties.Resources.NewReportActivity;
					case NetActivityTypes.FrequencyChanged:
						return Properties.Resources.FrequencyChangedActivity;
					default:
						return string.Empty;
				}
			}
		}

		private string _details;
		public string Details
		{
			get
			{
				return _details ?? string.Empty;
			}
			protected set
			{
				_details = value;
				if ( _details != null )
				{
					foreach ( string item in NetActivation.PriorityKeywords )
					{
						if ( _details.Contains( item ) )
						{
							IsPriority = true;
							return;
						}
					}
				}
				IsPriority = false;
			}
		}

		private NetMember _member;
		public NetMember Member
		{
			get
			{
				return _member;
			}
		}

		private NetLocation _location;
		public NetLocation Location
		{
			get
			{
				return _location;
			}
			protected set
			{
				_location = value;
				_location.PropertyChanged += new PropertyChangedEventHandler( _location_PropertyChanged );
			}
		}

		public NetActivity( DateTimeOffset time, NetActivityTypes activityType, string details, NetMember member )
		{
			_id = Guid.NewGuid();
			_loggerId = NetActivation.Instance.LoggerId;
			_activationId = NetActivation.Instance.ActivationId;
			_needsAck = false;
			_isLocal = true;
			_time = time;
			_activityType = activityType;
			Details = details;
			_member = member;
			_location = member.Location;
		}

		public NetActivity( DateTimeOffset time, NetActivityTypes activityType, string details )
		{
			_id = Guid.NewGuid();
			_loggerId = NetActivation.Instance.LoggerId;
			_activationId = NetActivation.Instance.ActivationId;
			_needsAck = false;
			_isLocal = true;
			_time = time;
			_activityType = activityType;
			Details = details;
			_location = new NetLocation();
		}

		void _location_PropertyChanged( object sender, PropertyChangedEventArgs e )
		{
			if ( e.PropertyName == "Location" )
				OnPropertyChanged( "Location" );
		}

		public NetActivity( XElement node )
		{
			foreach ( var item in node.Elements() )
			{
				switch ( item.Name.LocalName )
				{
					case "roster_id":
						_member = NetActivation.Instance.GetMember( NetPost.DecodedString( item ) );
						break;
					case "activity_time":
						_time = NetPost.FromMySQLDate( item );
						break;
					case "type_code":
						_activityType = ( NetActivityTypes ) ( int ) item;
						break;
					case "details":
						_details = NetPost.DecodedString( item );
						break;
					case "activity_id":
						_id = Guid.Parse( NetPost.DecodedString( item ) );
						break;
					case "is_priority":
						_isPriority = NetPost.ToBoolean( item );
						break;
					case "needs_ack":
						_needsAck = NetPost.ToBoolean( item );
						break;
				}
			}

			_location = new NetLocation( node );
			if ( _activityType == NetActivityTypes.NewReport )
				_member.AddReport( this );
		}

		public override bool Equals( object obj )
		{
			if ( obj is NetActivity )
			{
				return ( ( NetActivity ) obj )._id == _id;
			}
			else
				return false;
		}

		public override int GetHashCode()
		{
			return _id.GetHashCode();
		}

		public void OnMemberCallsignNameUpdated()
		{
			OnPropertyChanged( "Member" );
		}

		public NetPost GetNetPost()
		{
			NetPost
				post;

			if ( _isLocal )
			{
				post = new NetPost( NetActivation.ActivityPage );
				post.Data[ "net_id" ] = _activationId.ToString();
				if ( _member != null )
					post.Data[ "roster_id" ] = _member.Callsign;
				post.Data[ "logger_id" ] = _loggerId;
				post.Data[ "activity_time" ] = NetPost.ToMySQLDate( _time );
				if ( _location.IsDefined )
				{
					post.Data[ "location" ] = _location.Location;
					post.Data[ "latitude" ] = _location.Latitude.ToString();
					post.Data[ "longitude" ] = _location.Longitude.ToString();
				}
				post.Data[ "type_code" ] = ( ( int ) _activityType ).ToString();
				post.Data[ "type_descrip" ] = ActivityType;
				post.Data[ "details" ] = _details;
				post.Data[ "activity_id" ] = _id.ToString();
				post.Data[ "is_priority" ] = NetPost.FromBoolean( _isPriority );
			}
			else
				post = null;

			return post;
		}

		public bool IsVisible
		{
			get
			{
				return _location.IsVerified;
			}
		}

		public string Label
		{
			get
			{
				return string.Format( "{0} {1}", _member.Callsign, TimeString );
			}
		}

		public double Latitude
		{
			get
			{
				return _location.Latitude;
			}
		}

		public double Longitude
		{
			get
			{
				return _location.Longitude;
			}
		}

		public string IconFile
		{
			get
			{
				return NetMember.ReportIconFile;
			}
		}

		public bool Equals( INetMapMarker other )
		{
			return Latitude == other.Latitude && Longitude == other.Longitude;
		}
	}
}
